package org.amos.core.basic.utils.crud;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.SneakyThrows;
import org.amos.core.basic.annotation.MpQuery;
import org.amos.core.basic.enums.SqlKeyWordEnum;
import org.amos.core.basic.utils.AmosUtils;
import org.amos.core.basic.utils.FieldUtils;
import org.amos.core.basic.utils.JsonUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;

/**
 * @desc: mybatisPlus 注解化构造
 * @author: liubt
 * @date: 2021-01-04 19:21
 **/
public class WrapperBuilder<T, E> {

    @SneakyThrows
    public <E> QueryWrapper<E> build(T t) {
        QueryWrapper<E> wrapper = new QueryWrapper<>();
        Class<?> clazz = t.getClass();
        // 获取被Wrapper 标注的fields
        List<Field> fields = FieldUtils.getFieldsListWithAnnotation(clazz, MpQuery.class);

        String orderName = StrUtil.EMPTY;
        String orderBy = StrUtil.EMPTY;
        for (Field field : fields) {
            field.setAccessible(true);
            MpQuery annotationMpQuery = field.getAnnotation(MpQuery.class);
            if (Objects.nonNull(annotationMpQuery)) {
                Object fieldValue = field.get(t);
                SqlKeyWordEnum keyword = annotationMpQuery.keyword();
                String columnName = annotationMpQuery.column();

                if (ObjectUtil.isNotEmpty(fieldValue)) {
                    switch (keyword) {
                        case EQ:
                            wrapper.eq(columnName, fieldValue);
                            break;
                        case NE:
                            wrapper.ne(columnName, fieldValue);
                            break;
                        case GT:
                            wrapper.gt(columnName, fieldValue);
                            break;
                        case LT:
                            wrapper.lt(columnName, fieldValue);
                            break;
                        case GE:
                            wrapper.ge(columnName, fieldValue);
                            break;
                        case LE:
                            wrapper.le(columnName, fieldValue);
                            break;
                        case START_WITH:
                            wrapper.likeLeft(columnName, fieldValue);
                            break;
                        case END_WITH:
                            wrapper.likeRight(columnName, fieldValue);
                            break;
                        case LIKE:
                            wrapper.like(columnName, fieldValue);
                            break;
                        case NOT_LIKE:
                            wrapper.notLike(columnName, fieldValue);
                            break;
                        case IN:
                            wrapper.in(columnName, fieldValue);
                            break;
                        case NOT_IN:
                            wrapper.notIn(columnName, fieldValue);
                            break;
                        case BETWEEN:
                            BetweenCondition condition = JsonUtils.jsonToPojo((String) fieldValue, BetweenCondition.class);
                            wrapper.between(columnName, condition.getStart(), condition.getEnd());
                            break;
                        case NOT_BETWEEN:
                            BetweenCondition notCondition = JsonUtils.jsonToPojo((String) fieldValue, BetweenCondition.class);
                            wrapper.notBetween(columnName, notCondition.getStart(), notCondition.getEnd());
                            break;
                        case ORDER_NAME:
                            orderName = AmosUtils.toUnderScoreCase(String.valueOf(fieldValue));
                            break;
                        case ORDER_BY:
                            orderBy = String.valueOf(fieldValue);
                            break;
                    }
                }
            }
        }
        if (StrUtil.isAllNotBlank(orderName, orderBy)) {
            if (orderBy.equalsIgnoreCase(SqlKeyWordEnum.ASC.name())) {
                wrapper.orderByAsc(orderName);
            } else {
                wrapper.orderByDesc(orderName);
            }
        }
        return wrapper;
    }
}
